/*
 * Copyright 2009, 2010, YUNNAN Co-soft Information Technology Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.cs.website.client.remote.impl;

import com.cs.web.Keys;
import com.cs.web.client.action.ActionException;
import com.cs.web.client.remote.AbstractRemoteService;
import com.cs.web.model.User;
import com.cs.web.service.LangPropsService;
import com.cs.web.util.EmailSender;
import com.cs.web.util.Files;
import com.cs.web.util.Locales;
import com.cs.website.client.StatusCodes;
import com.cs.website.client.captcha.CaptchaServlet;
import com.cs.website.model.Contact;
import com.cs.website.model.Message;
import com.google.inject.Inject;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.jabsorb.JSONRPCBridge;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Mail service for JavaScript client.
 *
 * @author <a href="mailto:toughPatient5@gmail.com">Gang Liu</a>
 * @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
 * @version 1.0.1.0, Jun 16, 2010
 */
public final class MailService extends AbstractRemoteService {

    /**
     * Generated serial version uid.
     */
    private static final long serialVersionUID = 2547731736227195231L;
    /**
     * Logger.
     */
    private static Logger LOGGER = Logger.getLogger(MailService.class);
    /**
     * Mail send timeout.
     */
    private static final long TIMEOUT = 10 * 1000;
    /**
     * Language service.
     */
    @Inject
    private LangPropsService langPropsService;
    /**
     * Mail account configurations.
     */
    private static final ResourceBundle MAIL_ACCOUNT_CONFIG =
            ResourceBundle.getBundle("mail");

    /**
     * Public constructor with parameter. Invokes constructor of superclass.
     *
     * @param jsonRpcBridge the specified json rpc bridge.
     */
    @Inject
    public MailService(final JSONRPCBridge jsonRpcBridge) {
        super(jsonRpcBridge);
    }

    /**
     * Sends email.
     *
     * @param requestJSONObject the specified request json object, for example:
     * <pre>
     * {
     *     "contactorName": "Liang Ding",
     *     "contactorEmailAddress": "DL88250@gmail.com",
     *     "contactorPhoneNumber": "15308801236",
     *     "capCode": "zip3",
     *     "contactorMessage": "Message example"
     * }
     * @param request the specified request
     * @return for example:
     * {
     *     "msgs": {
     *         "mailSent": "Email Sent"
     *     },
     *     "sc": "EMAIL_SENT_SUCC"
     * }
     * @throws ActionException action exception
     */
    public JSONObject sendMail(final JSONObject requestJSONObject,
                               final HttpServletRequest request)
            throws ActionException {
        final JSONObject ret = new JSONObject();

        try {
            final String contactorName = requestJSONObject.getString(
                    Contact.CONTACTOR_NAME);
            final String contactorEmail = requestJSONObject.getString(
                    Contact.CONTACTOR_EMAIL_ADDRESS);
            final String contactorMessage = requestJSONObject.getString(
                    Contact.CONTACTOR_MESSAGE);
            final String contatorCapCode = requestJSONObject.getString(
                    Contact.CAP_CODE);
            final String actualCapCode = request.getSession().getAttribute(
                    CaptchaServlet.CAP_STRING).toString();

            final String contactorPhone = requestJSONObject.getString(
                    Contact.CONTACTOR_PHONE_NUMBER);
            boolean isValid = true;

            final Locale locale = Locales.getLocale(request);
            final JSONObject messages = new JSONObject();
            ret.put(Keys.MESSAGES, messages);
            if (!isValid(contactorName)) {
                messagesFill(messages, Message.NAME_CANNOT_BE_NULL, locale);
                isValid = false;
            }
            if (!isValid(contactorEmail)) {
                messagesFill(messages, Message.EMAIL_CANNOT_BE_NULL, locale);
                isValid = false;
            } else {
                if (!checkValidEmailAddress(contactorEmail)) {
                    messagesFill(messages, Message.ILLEGAL_EMAIL_ADDRESS, locale);
                    isValid = false;
                }
            }
            if (!isValid(contactorMessage)) {
                messagesFill(messages, Message.MESSAGE_CANNOT_BE_NULL, locale);
                isValid = false;
            }
            if (!isValid(contatorCapCode)) {
                messagesFill(messages, Message.CAPCODE_CANNOT_BE_NULL, locale);
                isValid = false;
            } else {
                if (!actualCapCode.equalsIgnoreCase(contatorCapCode)) {
                    messagesFill(messages, Message.CAPCODE_INCORRECT, locale);
                    isValid = false;
                }
            }

            if (isValid) {
                final String messageBody = genMessageBody(contactorName,
                                                          contactorEmail,
                                                          contactorPhone,
                                                          contactorMessage);
                final Thread task = new Thread(
                        new EmailSender(MAIL_ACCOUNT_CONFIG.getString(User.USER_NAME),
                                        MAIL_ACCOUNT_CONFIG.getString(User.USER_PASSWORD),
                                        MAIL_ACCOUNT_CONFIG.getString(User.USER_NAME), // email from
                                        MAIL_ACCOUNT_CONFIG.getString(User.USER_NAME), // email to
                                        messageBody,
                                        "Visitor message from co-soft.info"));
                try {
                    messagesFill(messages, Message.MAIL_SENT, locale);
                    ret.put(Keys.STATUS_CODE, StatusCodes.EMAIL_SENT_SUCC);

                    task.join(TIMEOUT);
                    LOGGER.info("Mail sending[sessionId=" + request.getSession().
                            getId() + "]....");
                    task.start();
                } catch (final InterruptedException e) {
                    messagesFill(messages, Message.MAIL_SENT_FAIL, locale);
                    ret.put(Keys.STATUS_CODE, StatusCodes.EMAIL_SENT_FAIL_);
                }
            } else {
                ret.put(Keys.STATUS_CODE,
                        com.cs.web.FwkStatusCodes.INPUT_INVALID);
            }

        } catch (final JSONException e) {
            LOGGER.error(e.getMessage(), e);
            throw new ActionException(e);
        }

        LOGGER.info("Mail sent[ret=" + ret + ", sessionId="
                + request.getSession().getId() + "]");

        return ret;
    }

    private String genMessageBody(final String contactorName,
                                  final String contactorEmail,
                                  final String contactorPhone,
                                  final String contactorMessage) {
        final StringBuilder bodyBuilder = new StringBuilder();

        bodyBuilder.append("Name: ");
        bodyBuilder.append(contactorName);
        bodyBuilder.append(Files.LINE_SEPARATOR);
        bodyBuilder.append("Email: ");
        bodyBuilder.append(contactorEmail);
        bodyBuilder.append(Files.LINE_SEPARATOR);
        bodyBuilder.append("Phone: ");
        bodyBuilder.append(contactorPhone);
        bodyBuilder.append(Files.LINE_SEPARATOR);
        bodyBuilder.append("Message: ");
        bodyBuilder.append(contactorMessage);

        return bodyBuilder.toString();
    }

    private boolean isValid(final String target) {
        return ((target != null) && (target.trim().length() != 0));
    }

    private boolean checkValidEmailAddress(final String address) {
        Pattern p = Pattern.compile("\\w+@(\\w+.)+[a-z]{2,3}");
        Matcher m = p.matcher(address);
        return m.matches();
    }

    private void messagesFill(final JSONObject messages,
                              final String key, final Locale locale)
            throws JSONException {
        messages.put(key, langPropsService.get(Keys.MESSAGES, key, locale));
    }
}
